package com.fmatos.amazingwallpapers.image.database;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.fmatos.amazingwallpapers.image.database.dto.ImageRow;
import com.fmatos.amazingwallpapers.imagemanagement.FileManager;

//Read this article: kagii.com/post/6828016869/android-sqlite-locking 
// The clue is to keep one connection to database when writing from different threads
@Deprecated
public class ImagesDataSource {

	private static final String TAG = ImagesDataSource.class.getSimpleName();
    private static final int FILES_TO_NOT_DELETE = 100;

    private SQLiteDatabase database;
	private ImagesDatabaseOpenHelper dbHelper;
	private Context context;

	private boolean isOpen = false;


	public ImagesDataSource(Context context) {
		dbHelper = new ImagesDatabaseOpenHelper(context);
        this.context = context;
	}

	/**
	 * Opens DB, this may take a long time so you better don't call it in onCreate
	 * @throws SQLException
	 */
	public void open() throws SQLException {
		database = dbHelper.getReadableDatabase();
		isOpen = true;
	}

	public void close() {
		isOpen = false;
		dbHelper.close();
	}

	/**
	 * Creates a row for the image, assuming it doesn't already exist. 
	 * TODO this method should be private, so it doesn't throw unique exception errors 
	 * @param url
	 * @param caption
	 * @return
	 */
//	public ImageRow createImageRow(String url, String caption,String album,String description) {
//		ContentValues values = new ContentValues();
//		values.put(ImagesDatabaseOpenHelper.COLUMN_ALBUM, album);
//		values.put(ImagesDatabaseOpenHelper.COLUMN_URL,url);
//		
//		values.put(ImagesDatabaseOpenHelper.COLUMN_CAPTION,caption);		
//		values.put(ImagesDatabaseOpenHelper.COLUMN_DESCRIPTION, description);
//		
//		long insertId = database.insert(ImagesDatabaseOpenHelper.TABLE_IMAGES, null,
//				values);
//		Cursor cursor = database.query(ImagesDatabaseOpenHelper.TABLE_IMAGES,
//		    ImagesDatabaseOpenHelper.ALL_COLUMNS, ImagesDatabaseOpenHelper.COLUMN_ID + " = " + insertId, null,
//				null, null, null);
//		cursor.moveToFirst();
//		ImageRow newImage = cursorToImage(cursor);
//		cursor.close();
//		
//		return newImage;
//	}

	public ImageRow getImageFromUrl(String url) {

		if ( isOpen && url == null || url.length() == 0) {
			return null;
		}
		
		String select = buildWhereClauseWithUrl(url);
		
		Cursor cursor = database.query(ImagesDatabaseOpenHelper.TABLE_IMAGES,
		    ImagesDatabaseOpenHelper.ALL_COLUMNS, select, null, null, null, null);

		ImageRow imageRow = null;
		cursor.moveToFirst();
		if (!cursor.isAfterLast()) {
			 imageRow = cursorToImage(cursor);
		}	
		
		// make sure to close the cursor
		cursor.close();
		return imageRow;
		
	}
	
	/**
	 * updates filepath for row given url
	 * @param row
	 */
	public void updateFilename(ImageRow row) {
		
		String whereClause = buildWhereClauseWithUrl(row.getUrl());
		
		ContentValues values = new ContentValues();
		values.put(ImagesDatabaseOpenHelper.COLUMN_FILEPATH,row.getFile()); //These Fields should be your String values of actual column names
		
		database.update(ImagesDatabaseOpenHelper.TABLE_IMAGES, values, whereClause , null);
		
	}
	
	private String buildWhereClauseWithUrl(String url) {
		return ImagesDatabaseOpenHelper.COLUMN_URL + "='" + url + "'";
	}
	
//	public void deleteImage(ImageRow image) {
//		long id = image.getId();
//		System.out.println("Comment deleted with id: " + id);
//		database.delete(ImagesDatabaseOpenHelper.TABLE_IMAGES, ImagesDatabaseOpenHelper.COLUMN_ID
//				+ " = " + id, null);
//	}

	/**
	 * Get all images given a where clause
	 * @param whereClause
	 * @return
	 */
	private List<ImageRow> getImages(String whereClause) {
		List<ImageRow> imageRowList = new ArrayList<ImageRow>();

		Cursor cursor = database.query(ImagesDatabaseOpenHelper.TABLE_IMAGES,
		    ImagesDatabaseOpenHelper.ALL_COLUMNS, whereClause, null, null, null, ImagesDatabaseOpenHelper.COLUMN_ID);

		cursor.moveToFirst();
		while (!cursor.isAfterLast()) {
			ImageRow comment = cursorToImage(cursor);
			imageRowList.add(comment);
			cursor.moveToNext();
		}
		// make sure to close the cursor
		cursor.close();
		
		Log.i(TAG,"Got " + imageRowList.size() + " images from DB" );
		return imageRowList;
	}

	private ImageRow cursorToImage(Cursor cursor) {
		ImageRow row = new ImageRow();
		row.setAlbum(cursor.getString(0));
		row.setId(cursor.getLong(1));		
		row.setUrl(cursor.getString(2));
		
		row.setFile(cursor.getString(3));
		row.setCaption(cursor.getString(4));
		row.setDescription(cursor.getString(5));
//		Log.d(TAG,"Cursor got image " + row.getId() + " with url " + row.getUrl() + " and caption " + row.getCaption());
		return row;
	}

	public boolean isOpen() {
		return isOpen;
	}


	/**
	 * Gets all images contained in all albums (TODO)
	 * @return
	 */
	public List<ImageRow> getAllImages() {
		return getImages(null);
	}
	
	
	/**
	 * Returns images that have already downloaded files. To be used to
     * display the latest images only
	 * @return
	 */
	public List<ImageRow> getImagesWithFiles() {
        // TODO display only the last 100 images or something like that
		return getImages(ImagesDatabaseOpenHelper.COLUMN_FILEPATH + " not null");
		
	}

    public List<ImageRow> getLatestImagesWithoutFiles() {
        // TODO get the last 100 images, and select those without files
        List <ImageRow> list =  getImages(ImagesDatabaseOpenHelper.COLUMN_FILEPATH + " is null");

        if ( list != null ) {
            int end = list.size();
            int start = end - FILES_TO_NOT_DELETE;
            if (start > 0) {
                list = list.subList(start, end);
            }
        }

        return list;
    }

	@Deprecated() 
	/**
	 * Replace this method by a cursor that does the same thing
	 * @param albumName
	 * @return
	 */
	public List<ImageRow> getAlbumByName(String albumName) {
		return getImages(ImagesDatabaseOpenHelper.COLUMN_ALBUM + "='" + albumName + "'");
	}

	public Cursor queryAlbums() {
		
		String groupBy = ImagesDatabaseOpenHelper.COLUMN_ALBUM;
		String whereClause = null;// ImagesDatabaseOpenHelper.COLUMN_FILEPATH + " NOT NULL";
		String orderBy = ImagesDatabaseOpenHelper.COLUMN_ID + " desc";
		
		return database.query(true, ImagesDatabaseOpenHelper.TABLE_IMAGES,
				null,whereClause, 
				null,
				groupBy ,null,orderBy, null, null);
	}

// TODO move this to downloadManager
    /**
     * Use some criteria to find old images and delete them from DB
     */
    public void deleteOldBitmaps() {
//        Log.i(TAG,"Mock that I'm deleting old bitmaps");

        List<ImageRow> fullList = getImagesWithFiles();
        int imagesToDelete = fullList.size() - FILES_TO_NOT_DELETE;
        if  ( imagesToDelete < 1) {
            Log.i(TAG,"Not enough images to be deleted");
            return;
        }
        List<ImageRow> list = fullList.subList(0,imagesToDelete);

        FileManager fmanager = new FileManager(context);
        int deleteCount = 0;
        int failedDeleteCount = 0;
        for (ImageRow image : list) {
            if ( image.getFile() != null ) {
                if ( fmanager.deleteFile(image.getFile()) ) {
                    deleteCount++;
                    image.setFile(null);
                    updateFilename(image);
                } else {
                    failedDeleteCount ++;
                }
            }
        }

        Log.i(TAG,"DB has " + fullList.size() + " entries");
        Log.i(TAG,"Found " + list.size() + " old images");
        Log.i(TAG,"  succedded  " + deleteCount + " times");
        Log.i(TAG,"  failed  " + failedDeleteCount + " times");

    }

    // TODO move to downloadmanager
    /**
     * Finds images on folder that don't have any album assigned and delete them
     */
    public void findLooseImages() {
        Log.i(TAG,"Mock that I'm deleting loose images");

        FileManager fmanager = new FileManager(context);

        String path = fmanager.getGalleryFolderPath();
        if ( path != null ) {
            File folder = new File(path);
            File files[] = folder.listFiles();

            int deleteCount = 0;
            int failedDeleteCount = 0;

            Log.d("Files", "Size: " + files.length);
            for (int i = 0; i < files.length; i++) {
                Log.d("Files", "FileName:" + files[i].getName());

                String fullpath = path + "/" + files[i].getName();
                List<ImageRow> list = getImages(ImagesDatabaseOpenHelper.COLUMN_FILEPATH + "='" +  fullpath + "'");
                if ( list != null && list.size() == 0) {
                    Log.i(TAG,"Image doesn't have a DB entry, delete it: " + fullpath   );
                    if ( fmanager.deleteFile(fullpath) ) {
                        deleteCount++;
                    } else {
                        failedDeleteCount++;
                    }

                }

            }

            if ( files != null ) {
                Log.i(TAG, "Found " + files.length + " images in folder");
            }
            Log.i(TAG,"  succedded  " + deleteCount + " times");
            Log.i(TAG,"  failed  " + failedDeleteCount + " times");
        }
    }


}